/*
 * Project: Sudoku Hint Engine for Android
 * Copyright (C) 2010-2013 Emanuel Moecklin
 * 
 * Available under the terms of the Lesser General Public License (LGPL)
 */
package com.onegravity.sudoku.solver;

import java.io.InputStream;
import java.net.MalformedURLException;

import android.net.Uri;

import com.onegravity.sudoku.solver.util.Logger;

/**
 * This class manages access to resources for the hint engine. 
 * @author Emanuel Moecklin
 */
public enum HintResource {
	
	// checks
	INCORRECT_DIGIT("hint_checks/IncorrectDigit", R.string.hint_incorrect_digit_name, R.string.hint_incorrect_digit_string, R.string.none),  
	INCORRECT_DIGITS("hint_checks/IncorrectDigits", R.string.hint_incorrect_digits_name, R.string.hint_incorrect_digits_string, R.string.none),  
	INCORRECT_DIGITS_NODETAILS("hint_checks/IncorrectDigits", R.string.hint_incorrect_digits_nodetails_name, R.string.hint_incorrect_digits_nodetails_string, R.string.none),  
	PENCIL_MARKS_2_ELIMINATE("hint_checks/PencilMarks2Eliminate", R.string.hint_pencil_marks_2eliminate_name, R.string.hint_pencil_marks_2eliminate_string, R.string.none),  
	INCORRECT_PENCIL_MARKS("hint_checks/IncorrectPencilMarks", R.string.hint_incorrect_pencil_marks_name, R.string.hint_incorrect_pencil_marks_string, R.string.none),  
	MISSING_PENCIL_MARKS("hint_checks/MissingPencilMarks", R.string.hint_missing_pencil_marks_name, R.string.hint_missing_pencil_marks_string, R.string.none),  
	SOLUTION("hint_checks/Solution", R.string.hint_solution_name, R.string.hint_solution_string, R.string.none),  
	NO_SOLUTION("hint_checks/NoSolution", R.string.hint_no_solution_name, R.string.hint_no_solution_string, R.string.none),  
	MULTIPLE_SOLUTIONS("hint_checks/MultipleSolutions", R.string.hint_multiple_solutions_name, R.string.hint_multiple_solutions_string, R.string.none),  
	SUDOKU_SOLVED("hint_checks/SudokuSolved", R.string.hint_solved_name, R.string.hint_solved_string, R.string.none),  
	ANALYSIS("hint_checks/Analysis", R.string.hint_analysis_name, R.string.hint_analysis_string, R.string.none),  
	ANALYSIS_FAILED("hint_checks/AnalysisFailed", R.string.hint_analysis_failed_name, R.string.hint_analysis_failed_string, R.string.none), 
	ANALYSIS_PUZZLE_2_DIFFICULT("hint_checks/AnalysisBeyondNightmare", R.string.hint_analysis_failed_name, R.string.hint_analysis_failed_string, R.string.none), 
	NO_HINTS("hint_checks/NoHints", R.string.hint_no_hints_name, R.string.hint_no_hints_string, R.string.none),  
	TOO_FEW_GIVENS("hint_checks/TooFewGivens", R.string.hint_too_few_givens_name, R.string.hint_too_few_givens_string, R.string.none),  
	
	// rules
	HIDDEN_SINGLE("hint_rules/hidden/HiddenSingle", R.string.hint_hidden_single_name, R.string.hint_hidden_single_name, R.string.hint_hidden_single_url),  
	FULL_HOUSE("hint_rules/hidden/FullHouse", R.string.hint_full_house_name, R.string.hint_full_house_name, R.string.hint_full_house_url),  

	// intersections
	CLAIMING("hint_rules/fish/SimpleLocking", R.string.hint_claiming_name, R.string.hint_claiming_string, R.string.hint_claiming_url),  
	POINTING("hint_rules/fish/SimpleLocking", R.string.hint_pointing_name, R.string.hint_pointing_string, R.string.hint_pointing_url),  
	
	// hidden subset
	HIDDEN_PAIR("hint_rules/hidden/HiddenSubset", R.string.hint_hidden_pair_name, R.string.hint_hidden_pair_name, R.string.hint_hidden_pair_url),  
	HIDDEN_TRIPLE("hint_rules/hidden/HiddenSubset", R.string.hint_hidden_triple_name, R.string.hint_hidden_triple_name, R.string.hint_hidden_triple_url),  
	HIDDEN_QUAD("hint_rules/hidden/HiddenSubset", R.string.hint_hidden_quad_name, R.string.hint_hidden_quad_name, R.string.hint_hidden_quad_url),  

	// naked subset
	NAKED_SINGLE("hint_rules/naked/NakedSingle", R.string.hint_naked_single_name, R.string.hint_naked_single_name, R.string.hint_naked_single_url),  
	NAKED_SINGLE_NO_CAND("hint_rules/naked/NakedSingleNoCand", R.string.hint_naked_single_name, R.string.hint_naked_single_name, R.string.hint_naked_single_url),  
	NAKED_PAIR("hint_rules/naked/NakedSubset", R.string.hint_naked_pair_name, R.string.hint_naked_pair_name, R.string.hint_naked_pair_url),  
	NAKED_TRIPLE("hint_rules/naked/NakedSubset", R.string.hint_naked_triple_name, R.string.hint_naked_triple_name, R.string.hint_naked_triple_url),  
	NAKED_QUAD("hint_rules/naked/NakedSubset", R.string.hint_naked_quad_name, R.string.hint_naked_quad_name, R.string.hint_naked_quad_url),  

	// fish
	XWING("hint_rules/fish/SimpleFish", R.string.hint_xwing_name, R.string.hint_xwing_name, R.string.hint_xwing_url),  
	SWORDFISH("hint_rules/fish/SimpleFish", R.string.hint_swordfish_name, R.string.hint_swordfish_name, R.string.hint_swordfish_url),  
	JELLYFISH("hint_rules/fish/SimpleFish", R.string.hint_jellyfish_name, R.string.hint_jellyfish_name, R.string.hint_jellyfish_url),  
	FINNED_XWING("hint_rules/fish/FinnedFish", R.string.hint_finned_xwing_name, R.string.hint_finned_xwing_name, R.string.hint_finned_xwing_url),  
	FINNED_SWORDFISH("hint_rules/fish/FinnedFish", R.string.hint_finned_swordfish_name, R.string.hint_finned_swordfish_name, R.string.hint_finned_swordfish_url),  
	FINNED_JELLYFISH("hint_rules/fish/FinnedFish", R.string.hint_finned_jellyfish_name, R.string.hint_finned_jellyfish_name, R.string.hint_finned_jellyfish_url),  
	SASHIMI_XWING("hint_rules/fish/SashimiFish", R.string.hint_sashimi_xwing_name, R.string.hint_sashimi_xwing_name, R.string.hint_sashimi_xwing_url),  
	SASHIMI_SWORDFISH("hint_rules/fish/SashimiFish", R.string.hint_sashimi_swordfish_name, R.string.hint_sashimi_swordfish_name, R.string.hint_sashimi_swordfish_url),  
	SASHIMI_JELLYFISH("hint_rules/fish/SashimiFish", R.string.hint_sashimi_jellyfish_name, R.string.hint_sashimi_jellyfish_name, R.string.hint_sashimi_jellyfish_url),  

	// wings
	WWING("hint_rules/wings/WWing", R.string.hint_w_wing_name, R.string.hint_w_wing_name, R.string.hint_w_wing_url),  
	XYWING("hint_rules/wings/XYWing", R.string.hint_xy_wing_name, R.string.hint_xy_wing_name, R.string.hint_xy_wing_url),  
	XYZWING("hint_rules/wings/Wing", R.string.hint_xyz_wing_name, R.string.hint_xyz_wing_name, R.string.hint_xyz_wing_url),  
	WXYZWING("hint_rules/wings/Wing", R.string.hint_wxyz_wing_name, R.string.hint_wxyz_wing_name, R.string.hint_wxyz_wing_url),  
	VWXYZ_WING("hint_rules/wings/Wing", R.string.hint_vwxyz_wing_name, R.string.hint_vwxyz_wing_name, R.string.hint_vwxyz_wing_url),  
	UVWXYZ_WING("hint_rules/wings/Wing", R.string.hint_uvwxyz_wing_name, R.string.hint_uvwxyz_wing_name, R.string.hint_uvwxyz_wing_url),  
	TUVWXYZ_WING("hint_rules/wings/Wing", R.string.hint_tuvwxyz_wing_name, R.string.hint_tuvwxyz_wing_name, R.string.hint_tuvwxyz_wing_url),  
	STUVWXYZ_WING("hint_rules/wings/Wing", R.string.hint_stuvwxyz_wing_name, R.string.hint_stuvwxyz_wing_name, R.string.hint_stuvwxyz_wing_url),  
	RSTUVWXYZ_WING("hint_rules/wings/Wing", R.string.hint_rstuvwxyz_wing_name, R.string.hint_rstuvwxyz_wing_name, R.string.hint_rstuvwxyz_wing_url),  

	// uniqueness test
	UNIQUENESS_TEST_1("hint_rules/uniqueness/UniquenessTest1", R.string.hint_unique_name, R.string.hint_unique_name, R.string.hint_unique_1_url),  
	UNIQUENESS_TEST_2("hint_rules/uniqueness/UniquenessTest2and5", R.string.hint_unique_name, R.string.hint_unique_name, R.string.hint_unique_2_url),  
	UNIQUENESS_TEST_5("hint_rules/uniqueness/UniquenessTest2and5", R.string.hint_unique_name, R.string.hint_unique_name, R.string.hint_unique_5_url),  
	UNIQUENESS_TEST_3_HIDDEN("hint_rules/uniqueness/UniquenessTest3Hidden", R.string.hint_unique_name, R.string.hint_unique_name, R.string.hint_unique_3_url),  
	UNIQUENESS_TEST_3_NAKED("hint_rules/uniqueness/UniquenessTest3Naked", R.string.hint_unique_name, R.string.hint_unique_name, R.string.hint_unique_3_url),  
	UNIQUENESS_TEST_4("hint_rules/uniqueness/UniquenessTest4", R.string.hint_unique_name, R.string.hint_unique_name, R.string.hint_unique_4_url),  
	
	// bivalue universal grave (BUG)
	BUG_1("hint_rules/uniqueness/BivalueUniversalGrave1", R.string.hint_bug_name, R.string.hint_bug_name, R.string.hint_bug_url),  
	BUG_2("hint_rules/uniqueness/BivalueUniversalGrave2", R.string.hint_bug_name, R.string.hint_bug_name, R.string.hint_bug_url),
	BUG_3("hint_rules/uniqueness/BivalueUniversalGrave3", R.string.hint_bug_name, R.string.hint_bug_name, R.string.hint_bug_url),
	BUG_4("hint_rules/uniqueness/BivalueUniversalGrave4", R.string.hint_bug_name, R.string.hint_bug_name, R.string.hint_bug_url),
	AVOIDABLE_RECTANGLE_1("hint_rules/uniqueness/AvoidableRectangle1", R.string.hint_avoidablerectangle_name, R.string.hint_avoidablerectangle_name, R.string.hint_avoidablerectangle_url),  
	AVOIDABLE_RECTANGLE_2("hint_rules/uniqueness/AvoidableRectangle2", R.string.hint_avoidablerectangle_name, R.string.hint_avoidablerectangle_name, R.string.hint_avoidablerectangle_url),  
	HIDDEN_UNIQUE_RECTANGLE("hint_rules/uniqueness/HiddenUniqueRectangle", R.string.hint_hiddenuniquerectangle_name, R.string.hint_hiddenuniquerectangle_name, R.string.hint_hiddenuniquerectangle_url),  

	// aligned subset exclusion
	ALIGNED_PAIR_EXCLUSION("hint_rules/AlignedPairExclusion", R.string.hint_aligned_subset_exclusion_name, R.string.hint_aligned_subset_exclusion_name, R.string.hint_aligned_pair_exclusion_url), 
	ALIGNED_SUBSET_EXCLUSION("hint_rules/AlignedSubsetExclusion", R.string.hint_aligned_subset_exclusion_name, R.string.hint_aligned_subset_exclusion_name, R.string.hint_aligned_subset_exclusion_url), 

	// almost locked sets
	ALMOST_LOCKED_CANDIDATES_2("hint_rules/als/AlmostLockedCandidates2", R.string.hint_almostlockedcandidates_name, R.string.hint_almostlockedcandidates_name, R.string.hint_almostlockedcandidates_url), 
	ALMOST_LOCKED_CANDIDATES_N("hint_rules/als/AlmostLockedCandidatesN", R.string.hint_almostlockedcandidates_name, R.string.hint_almostlockedcandidates_name, R.string.hint_almostlockedcandidates_url), 
	ALMOST_LOCKED_SET_XZ("hint_rules/als/ALSXZ", R.string.hint_almostlockedset_xz_name, R.string.hint_almostlockedset_xz_name, R.string.hint_almostlockedset_xz_url), 
	ALMOST_LOCKED_SET_XY_WING("hint_rules/als/ALSXYWing", R.string.hint_almostlockedset_xy_wing_name, R.string.hint_almostlockedset_xy_wing_name, R.string.hint_almostlockedset_xy_wing_url), 
	ALMOST_LOCKED_SET_XY_CHAIN("hint_rules/als/ALSXYChain", R.string.hint_almostlockedset_xy_chain_name, R.string.hint_almostlockedset_xy_chain_name, R.string.none), 

	// chains
	FORCING_XCHAIN_TURBOT("hint_rules/chaining/ForcingXChainTurbot", R.string.hint_forcing_xchainturbot_name, R.string.hint_forcing_xchainturbot_name, R.string.hint_forcing_xchainturbot_url), 
	FORCING_XCHAIN("hint_rules/chaining/ForcingXChain", R.string.hint_forcing_xchain_name, R.string.hint_forcing_xchain_name, R.string.hint_forcing_xchain_url), 
	REMOTE_PAIRS("hint_rules/chaining/RemotePairs", R.string.hint_remote_pairs_name, R.string.hint_remote_pairs_name, R.string.hint_remote_pairs_url), 
	FORCING_XYCHAIN("hint_rules/chaining/ForcingXYChain", R.string.hint_forcing_xychain_name, R.string.hint_forcing_xychain_name, R.string.hint_forcing_xychain_url), 
	FORCING_CHAIN("hint_rules/chaining/ForcingChain", R.string.hint_forcing_chain_name, R.string.hint_forcing_chain_name, R.string.hint_forcing_chain_url), 

	BIDIRECTIONAL_XCYCLE("hint_rules/chaining/BidirectionalXCycle", R.string.hint_forcing_bidirectional_xcycle_name, R.string.hint_forcing_bidirectional_xcycle_name, R.string.hint_forcing_bidirectional_xcycle_url), 
	BIDIRECTIONAL_YCYCLE("hint_rules/chaining/BidirectionalYCycle", R.string.hint_forcing_bidirectional_ycycle_name, R.string.hint_forcing_bidirectional_ycycle_name, R.string.hint_forcing_bidirectional_ycycle_url), 
	BIDIRECTIONAL_CYCLE("hint_rules/chaining/BidirectionalCycle", R.string.hint_forcing_bidirectional_cycle_name, R.string.hint_forcing_bidirectional_cycle_name, R.string.hint_forcing_bidirectional_cycle_url), 
	
	NISHIO_FORCING_CHAIN("hint_rules/chaining/NishioForcingChain", R.string.hint_nishio_forcing_chain_name, R.string.hint_nishio_forcing_chain_name, R.string.hint_nishio_forcing_chain_url), 
	DYNAMIC_DOUBLE_FORCING_CHAIN("hint_rules/chaining/DynamicDoubleForcingChain", R.string.hint_dynamic_double_forcing_chain_name, R.string.hint_dynamic_double_forcing_chain_name, R.string.hint_dynamic_double_forcing_chain_url), 
	DYNAMIC_CONTRADICTION_CHAIN("hint_rules/chaining/DynamicContradictionChain", R.string.hint_dynamic_contradiction_chain_name, R.string.hint_dynamic_contradiction_chain_name, R.string.hint_dynamic_contradiction_chain_url), 
	REGION_FORCING_CHAIN("hint_rules/chaining/RegionForcingChain", R.string.hint_region_forcing_chain_name, R.string.hint_region_forcing_chain_name, R.string.hint_region_forcing_chain_url), 
	DYNAMIC_REGION_FORCING_CHAIN("hint_rules/chaining/DynamicRegionForcingChain", R.string.hint_dynamic_region_forcing_chain_name, R.string.hint_dynamic_region_forcing_chain_name, R.string.hint_region_forcing_chain_url), 
	CELL_FORCING_CHAIN("hint_rules/chaining/CellForcingChain", R.string.hint_cell_forcing_chain_name, R.string.hint_cell_forcing_chain_name, R.string.hint_cell_forcing_chain_url), 
	DYNAMIC_CELL_FORCING_CHAIN("hint_rules/chaining/DynamicCellForcingChain", R.string.hint_dynamic_cell_forcing_chain_name, R.string.hint_dynamic_cell_forcing_chain_name, R.string.hint_cell_forcing_chain_url), 

	SUE_DE_COQ("hint_rules/SueDeCoq", R.string.hint_sue_de_coq_name, R.string.hint_sue_de_coq_name, R.string.hint_sue_de_coq_url), 

	BRUTE_FORCE("hint_rules/BruteForce", R.string.hint_brute_force_name, R.string.hint_brute_force_name, R.string.none),  
	;

	// ****************************************** Static Methods *******************************************

	public static String getString(int resId, Object... formatArgs) {
		try {
			return HintEngine.getContext().getString(resId, formatArgs);
		}
		catch (Throwable t) {
			return ""; 
		}
	}
	
	public static InputStream getAsset(String fileName) {
    	try {
            return HintResource.class.getResourceAsStream(getString(R.string.HTML_RESOURCES) + fileName);
		}
    	catch (Exception e) {
        	Logger.e(HintResource.class.getSimpleName(), e.getMessage(), e);
        	return null;
		}
	}

	// ****************************************** Instance Methods *******************************************

	private String mLocation;
	private int mResIDName;
	private int mResIDString;
	private Uri mUrl;
	
	HintResource(String location, int resIDName, int resIDString, int urlID) {
		mLocation = location;
		mResIDName = resIDName;
		mResIDString = resIDString;
		String urlString = HintEngine.getContext().getString(urlID);
		try {
			new java.net.URL( urlString );					// let's validate the url before we use it
			mUrl = android.net.Uri.parse( urlString );		// validate url --> now we can use it
		}
		catch (MalformedURLException e) {
			mUrl = null;
		}
	}
	
	public String hint() {
		return mLocation + ".html";  
	}

	/**
	 * @return the Url link for this resource. If there's non Null will be returned.
	 */
	public Uri getUrl() {
		return mUrl;  
	}
	
	public String hint(HintType hintType) {
		switch(hintType) {
		case SMALL_CLUE:
			return mLocation + "_step1.html";  
		case BIG_CLUE:
			return mLocation + "_step2.html";  
		default:
			return mLocation + "_step3.html";  
		}
	}
	
	public String getName(Object... formatArgs) {
		try {
			return HintEngine.getContext().getString(mResIDName, formatArgs);
		}
		catch (Throwable t) {
			return ""; 
		}
	}
	
	public String toString() {
		return toString((Object) null);
	}
	
	public String toString(Object... formatArgs) {
		try {
			return HintEngine.getContext().getString(mResIDString, formatArgs);
		}
		catch (Throwable t) {
			return ""; 
		}
	}
	
}